What is logform?
The logform npm package is a module designed for formatting messages in logging systems, primarily used with the popular Winston logger. It provides a way to define how log messages should be formatted before they are written to a console, file, or any other transport.
What are logform's main functionalities?
Simple message formatting
This feature allows users to create custom message formats using the printf function from logform. It enables the inclusion of timestamp, label, level, and message in the log output.
const { format } = require('logform');
const { printf } = format;
const myFormat = printf(({ level, message, label, timestamp }) => {
return `${timestamp} [${label}] ${level}: ${message}`;
});
// Use this format in a Winston logger
Colorizing the output
This feature provides an easy way to add color to log messages based on the log level, enhancing readability especially when viewing logs directly from consoles.
const { format } = require('logform');
const { colorize } = format;
const colorizedFormat = colorize();
// This format can be used to add colors to different levels of log messages when used with Winston logger
Combining multiple formats
This feature allows the combination of multiple formatting methods such as adding labels, timestamps, and custom printf templates to create a highly customized log output.
const { format } = require('logform');
const { combine, timestamp, label, printf } = format;
const combinedFormats = combine(
label({ label: 'My App' }),
timestamp(),
printf(info => `${info.timestamp} [${info.label}] ${info.level}: ${info.message}`)
);
// This combined format can be used in a Winston logger to provide a rich structured output
Other packages similar to logform
winston
Winston is a multi-transport async logging library for Node.js. While logform is primarily used as a formatting tool within Winston, Winston itself provides more comprehensive logging solutions including transports management, which logform does not handle.
bunyan
Bunyan is another logging library that focuses on JSON logging. Unlike logform, which is used for formatting log messages, Bunyan handles both the logging and formatting but emphasizes a JSON structure for output, making it ideal for machine parsing.
pino
Pino is a very low overhead Node.js logger, similar to Bunyan but focuses on performance. It includes its own set of formatting capabilities but is generally used for its performance benefits over extensive formatting options.
logform
An mutable object-based log format designed for chaining & objectMode streams.
const { format } = require('logform');
const alignedWithColorsAndTime = format.combine(
format.colorize(),
format.timestamp(),
format.align(),
format.printf(info => `${info.timestamp} ${info.level}: ${info.message}`)
);
info
Objects
The info
parameter provided to a given format represents a single log message. The object itself is mutable. Every info
must have at least the level
and message
properties:
{
level: 'info',
message: 'Hey! Log something?'
}
logform
itself exposes several additional properties:
splat
: string interpolation splat for %d %s
-style messages.timestamp
: timestamp the message was received.label
: custom label associated with each message.
As a consumer you may add whatever properties you wish – internal state is maintained by Symbol
properties:
Symbol.for('level')
(READ-ONLY): equal to level
property. Is treated as immutable by all code.Symbol.for('message'):
complete string message set by "finalizing formats": json
, logstash
, printf
, prettyPrint
, and simple
.
Understanding formats
Formats are prototypal objects (i.e. class instances) that define a single method: transform(info, opts)
and return the mutated info
info
: an object representing the log message.opts
: setting specific to the current instance of the format.
They are expected to return one of two things:
- An
info
Object representing the modified info
argument. Object references need not be preserved if immutability is preferred. All current built-in formats consider info
mutable, but [immutablejs] is being considered for future releases. - A falsey value indicating that the
info
argument should be ignored by the caller. (See: Filtering info
Objects) below.
logform.format
is designed to be as simple as possible. To define a new format simple pass it a transform(info, opts)
function to get a new Format
.
The named Format
returned can be used to create as many copies of the given Format
as desired:
const { format } = require('logform');
const volume = format((info, opts) => {
if (opts.yell) {
info.message = info.message.toUpperCase();
} else if (opts.whisper) {
info.message = info.message.toLowerCase();
}
return info;
});
const scream = volume({ yell: true });
console.dir(scream.transform({
level: 'info',
message: `sorry for making you YELL in your head!`
}, scream.options));
const whisper = volume({ whisper: true });
console.dir(whisper.transform({
level: 'info',
message: `WHY ARE THEY MAKING US YELL SO MUCH!`
}), whisper.options);
Combining formats
Any number of formats may be combined into a single format using format.combine
. Since format.combine
takes no opts
, as a convenience it returns pre-created instance of the combined format.
const { format } = require('logform');
const { combine, timestamp, label } = format;
const labelTimestamp = combine(
label({ label: 'right meow!' }),
timestamp()
);
const info = labelTimestamp.transform({
level: 'info',
message: 'What time is the testing at?'
});
console.dir(info);
Filtering info
Objects
If you wish to filter out a given info
Object completely then simply return a falsey value.
const ignorePrivate = format((info, opts) => {
if (info.private) { return false; }
return info;
});
console.dir(ignorePrivate.transform({
level: 'error',
message: 'Public error to share'
}));
console.dir(ignorePrivate.transform({
level: 'error',
private: true,
message: 'This is super secret - hide it.'
}));
Use of format.combine
will respect any falsey values return and stop evaluation of later formats in the series. For example:
const { format } = require('logform');
const { combine, timestamp, label } = format;
const willNeverThrow = format.combine(
format(info => { return false })(),
format(info => { throw new Error('Never reached') })()
);
console.dir(willNeverThrow.transform({
level: 'info',
message: 'wow such testing'
}))
Tests
Tests are written with mocha
, assume
, and nyc
. They can be run with npm
:
npm test
LICENSE: MIT